home *** CD-ROM | disk | FTP | other *** search
- {══════════════════════════════ RUN123.PAS ═══════════════════════════════}
- { ─────────── Turbo 4.0/5.0 subprocess demonstration program ────────── }
- { Copyright (c) 1989 Richard W. Prescott }
- { This program can be used to run 123.COM, load a designated worksheet, }
- { and execute a series of keyboard entries (eg: printing a range, or }
- { executing a macro) as specified on the RUN123 command line. }
- { Illustrates how to modify the behavior of an existing program using }
- { interrupt routines and executing the program as a subprocess. }
- { }
- { The Unit INTR16 contains the assembly code for the basic interrupt }
- { routine, which is installed automatically by the "Uses INTR16" clause }
- { and is detached automatically by the INTR16 Exit Code. The assembly }
- { code within INTR16 traps all Interrupt $16 (BIOS Keyboard Services) }
- { requests and issues a FAR Call via the Pointer variable PascalCode }
- { which is initialized in the MAIN block (below) to point to the }
- { procedure StuffProc. StuffProc returns the next character from the }
- { command line for ReadChar and Status requests, chaining to the BIOS }
- { Interrupt $16 handler for keyboard shift state requests. }
- { }
- { The Unit INTR16 provides the (Assembly) Inline Directives IChain for }
- { chaining to the original interrupt routine, and IReturn for returning }
- { directly to the calling program. These may be called from any point }
- { within the Pascal code. The user registers at interrupt entry are }
- { accessible through the record variable User^ (User^.Ax, User^.Flags, }
- { etc). They should be modified as necessary to simulate a successful }
- { interrupt request before calling IReturn, as illustrated in the }
- { procedure StuffProc. }
- { }
- { The Unit T5DOS provides routines which are Call & Result compatible }
- { with GetEnv, FSearch, and SwapVectors from the Turbo 5.0 DOS Unit. }
- { They are used in the MAIN block (below) and are provided here for the }
- { benefit of Turbo 4.0 Users. }
- {══════════════════════════════ RUN123.PAS ═══════════════════════════════}
-
- {$M $2400,0,0}
-
- Uses DOS,
- {$IFDEF VER40} T5DOS, {$ENDIF}
- INTR16;
-
-
- LABEL
- Accumulate;
-
- VAR
- n,m: INTEGER;
- AltLetter: CHAR;
- SendScan: ARRAY[0..255] OF BYTE;
- TempStr: STRING[255];
- Path123: STRING[79];
- PathLen: BYTE Absolute Path123;
- SaveDir: STRING[67];
-
- CONST
- SendLine: STRING[255] = '';
- SendPos: Byte = 1;
-
- AltScan: ARRAY['A'..'Z'] OF BYTE = (
- {A} 30, {B} 48, {C} 46, {D} 32, {E} 18, {F} 33, {G} 34,
- {H} 35, {I} 23, {J} 36, {K} 37, {L} 38, {M} 50, {N} 49,
- {O} 24, {P} 25, {Q} 16, {R} 19, {S} 31, {T} 20, {U} 22,
- {V} 47, {W} 17, {X} 45, {Y} 21, {Z} 44 );
-
- MacroKey: ARRAY[1..25] OF
- RECORD
- Name: STRING[11]; Sc: BYTE; Ch: CHAR;
- END = (
- (Name: '{DOWN}'; Sc: 80; Ch: #0),
- (Name: '{UP}'; Sc: 72; Ch: #0),
- (Name: '{LEFT}'; Sc: 75; Ch: #0),
- (Name: '{RIGHT}'; Sc: 77; Ch: #0),
- (Name: '{HOME}'; Sc: 71; Ch: #0),
- (Name: '{END}'; Sc: 79; Ch: #0),
- (Name: '{PGUP}'; Sc: 73; Ch: #0),
- (Name: '{PGDN}'; Sc: 81; Ch: #0),
- (Name: '{BIGLEFT}'; Sc: 115; Ch: #0),
- (Name: '{BIGRIGHT}'; Sc: 116; Ch: #0),
- (Name: '{EDIT}'; Sc: 60; Ch: #0),
- (Name: '{NAME}'; Sc: 61; Ch: #0),
- (Name: '{ABS}'; Sc: 62; Ch: #0),
- (Name: '{GOTO}'; Sc: 63; Ch: #0),
- (Name: '{WINDOW}'; Sc: 64; Ch: #0),
- (Name: '{QUERY}'; Sc: 65; Ch: #0),
- (Name: '{TABLE}'; Sc: 66; Ch: #0),
- (Name: '{CALC}'; Sc: 67; Ch: #0),
- (Name: '{GRAPH}'; Sc: 68; Ch: #0),
- (Name: '{DEL}'; Sc: 83; Ch: #0),
- (Name: '{DELETE}'; Sc: 83; Ch: #0),
- (Name: '{ESC}'; Sc: 0; Ch: #27),
- (Name: '{ESCAPE}'; Sc: 0; Ch: #27),
- (Name: '{BS}'; Sc: 0; Ch: #08),
- (Name: '{BACKSPACE}'; Sc: 0; Ch: #08) );
-
-
- {═══════════════════════════════ StuffProc ═══════════════════════════════}
- { This is the Pascal code for the interrupt service routine, called from }
- { INTR16.IHook. For Read Character requests (User^.Ah = 0 or $10), }
- { return character and scan code of next character on the command line. }
- { For Read Status requests (User^.Ah = 1 or $11), clear User Zero Flag }
- { to indicate key waiting and report character and scan code of next }
- { character on the command line. For all other requests, chain to the }
- { BIOS Interrupt $16 handler. When the command line is empty, detach }
- { the interrupt routine to allow subsequent Keyboard Service requests to }
- { be handled by the BIOS. }
- {═══════════════════════════════ StuffProc ═══════════════════════════════}
- PROCEDURE StuffProc;
- BEGIN
- CASE User^.AH OF
-
- 0,$10: IF SendPos <= Length(SendLine) THEN BEGIN
- User^.AL := BYTE(SendLine[SendPos]);
- User^.AH := SendScan[SendPos];
- Inc(SendPos);
- Ireturn;
- END {0: IF SendPos <= Length(SendLine) THEN }
- ELSE BEGIN
- Irestore;
- Ichain;
- END; {ELSE }
-
- 1,$11: IF SendPos <= Length(SendLine) THEN BEGIN
- User^.AL := BYTE(SendLine[SendPos]);
- User^.AH := SendScan[SendPos];
- User^.Flags := User^.Flags AND $FFBF; {Clear ZF}
- Ireturn;
- END {0: IF SendPos <= Length(SendLine) THEN }
- ELSE BEGIN
- Irestore;
- Ichain;
- END; {ELSE }
-
- else Ichain;
-
- END; {CASE User.AH }
-
- END; {PROCEDURE StuffProc; }
-
-
- {══════════════════════════════════ MAIN ═════════════════════════════════}
- { Translate and store keystrokes indicated on command line, initialize }
- { PascalCode Pointer, change to 123 directory, and Exec 123.COM. On }
- { return, restore original directory. }
- {══════════════════════════════════ MAIN ═════════════════════════════════}
- BEGIN {- MAIN -}
- FillChar(SendScan,256,#0);
-
- {═════ Process Command Line for "~", Macro, and Alt- Key translation ═════}
-
- {═══ If first command is not "/", assume it is a file name to retrieve ═══}
- SendLine := ParamStr(1);
- IF (SendLine <> '')
- AND (SendLine[1] <> '/')
- THEN SendLine := '/fr' + ParamStr(1) + #13;
-
- For n := 2 TO ParamCount DO BEGIN
-
- TempStr := ParamStr(n);
-
- {════════════════════ Translate "~" to carriage return ═══════════════════}
- m := Pos('~',TempStr);
- WHILE m>0 DO BEGIN
- TempStr[m] := #13; m := Pos('~',TempStr);
- END; {WHILE m>0 DO }
-
- {═════════════════════════ Translate macro keys ══════════════════════════}
- IF TempStr[1]='{' THEN BEGIN
- FOR m := 1 TO Length(TempStr) DO TempStr[m] := UpCase(TempStr[m]);
- FOR m := 1 TO 25 DO IF TempStr = MacroKey[m].Name THEN BEGIN
- SendScan[ 1 + Length(SendLine) ] := MacroKey[m].Sc;
- TempStr := MacroKey[m].Ch;
- GOTO Accumulate;
- END; {FOR m := 1 TO 25 DO IF TempStr = MacroKey[m].Name THEN }
- WRITELN('Invalid Macro Key ',TempStr,' Specified'); Halt(2);
- END; {IF TempStr[1]='{' THEN }
-
- {══════════════════════════ Translate Alt- Keys ══════════════════════════}
- IF TempStr[1]='\' THEN BEGIN
- Delete(TempStr,1,1);
- AltLetter:= UpCase(TempStr[1]);
- IF NOT (AltLetter IN ['A'..'Z']) THEN BEGIN
- WRITELN('Invalid Macro \',AltLetter,' Specified'); Halt(2);
- END; {IF NOT AltLetter IN ('A'..'Z') THEN }
-
- SendScan[ 1 + Length(SendLine) ] := AltScan[AltLetter];
- TempStr[1] := #0;
- END; {IF TempStr[1]='\' THEN }
-
- {═══════════ Accumulate translated parameters in VAR SendLine ════════════}
- Accumulate:
- SendLine := SendLine + TempStr;
-
- END; {For n := 2 TO ParamCount DO }
-
-
- {══════════ Initialize PascalCode Pointer to StuffProc (above) ═══════════}
- PascalCode := @StuffProc;
-
- {════════════════ Search current Dir and Path for 123.COM ════════════════}
- Path123 := FSearch('123.COM',GetEnv('PATH'));
-
-
- {═════════════ If found, change directories and execute 123 ══════════════}
- IF Path123 = ''
- THEN WRITELN('123.COM NOT FOUND')
- ELSE BEGIN
- PathLen := Pos('123.COM',Path123) -1; {- Determine 123 Directory -}
- IF (Path123[PathLen] = '\') {- Remove trailing '\' -}
- AND (Path123[PathLen-1] <> ':') {- .. except for Root Dir -}
- THEN Dec(PathLen);
- GetDir(0,SaveDir); {- Save Current Directory -}
- IF Path123<>'' THEN ChDir(Path123); {- Change to 123 Directory -}
- SwapVectors;
- Exec('123.COM',''); {- Execute 123.COM -}
- SwapVectors;
- ChDir(SaveDir); {- Restore Directory -}
- END; {ELSE }
-
- END.
-